#encoding: utf-8
import datetime
import re
import random
import xlrd
import config
import json

# 判断日期格式
def validateDate(targettext):
    try:
        if datetime.datetime.strptime(str(targettext), '%Y-%m-%d'):
            return 1
    except ValueError:
        return 0

# 判断日期时间格式
def validateDatetime(targettext):
    try:
        if datetime.datetime.strptime(str(targettext), '%Y-%m-%d %H:%M:%S'):
            return 1
    except ValueError:
        return 0

# 根据value获取字典的key
def get_dict_key(dict, value):
    return [k for k, v in dict.items() if v == value]



# 生成字符串
def generateNums(numLen,isWithLeters=0):
    numStr1 = '8956056781234010123456789278923456778978012301234534560145678901223456782345667894569012334010178999'
    numStr2 = 'qazwRTYUIOZsxedcrfvtPLKJHGFDSAgbyhnujmikolpQWEXVCBNMqazwRTYUIOZsxedcrfvtPLKJHGFDSAgbyhnujmikolpQWEXM'
    if isWithLeters != 0:
        numStr = numStr1 + numStr2
    else:
        numStr = numStr1
    if numLen < 1 or not isinstance(numLen, int) or numLen > 50:
        return False
    if numLen < 19:
        result = ''.join(random.sample(numStr, numLen))
    else:
        result = datetime.datetime.now().strftime('%Y%m%d%H%M%S%f')[:18] + ''.join(random.sample(numStr, numLen-18))
    return result

# 将标点符号替换为指定的标点mark，mark为空时可以去除标点符号
def replaceMarks(text, mark):
    r='[!"#$%&\'()*+,-./:;——：；—‘’“”<=>?@[\\]^_`{|}~\n。，！]+'
    line=re.sub(r, mark,text)
    return line

# 判断字符串中是否有标点
def isContainMarks(text):
    test_str = re.search(r"\W", text)
    if test_str == None:
        return 1
    else:
        return 0

# 下拉菜单value转为key
def singleSelect_ValueToKey(myValue, myDict, default):
    if isContainMarks(myValue):
        if myValue in myDict.values():
            myKey = get_dict_key(myDict, myValue)[0]
        else:
            myKey = default
    else:
        myKey = default
    return myKey

# 验证excel数据
def checkExcelData(excel):
    try:
        feedbacksInfo = xlrd.open_workbook(excel)
        firstSheetName = feedbacksInfo.sheet_names()[0]
        if '反馈问题记录表' == firstSheetName:
            feedbackSheet = feedbacksInfo.sheet_by_name(firstSheetName)
            dataRows = feedbackSheet.nrows

            errorRowList = []

            if dataRows > config.IMPORT_MAX_ROWS + 2:
                msg = '获取到 %d 行数据，超过1000行，将只导入除表头以外的前1000行数据。' % (dataRows - 2)
                dataRows = 1002
            for i in range(2, dataRows):
                feedback_date = feedbackSheet.cell(i,1).value
                provider = str(feedbackSheet.cell(i,2).value)
                issue_desc = str(feedbackSheet.cell(i,4).value)
                reciver = str(feedbackSheet.cell(i,9).value)

                if not feedback_date or not provider or not issue_desc or not reciver:
                    errorRowList.append(i+1)
            if len(errorRowList) == 0:
                return 1
            else:
                msg = '第 %s 行数据有必填项为空，请检查【反馈日期、反馈人、问题描述、接收人】！' %(str(errorRowList))
                return msg

        else:
            msg = '导入失败，表格的第一个sheet名称必须为“反馈问题记录表”'
            return msg
    except Exception as e:
        return e

# 判断给定的字符串是否只包含字母、数字、中划线或者下划线中的一个或多个，并且以字母或数字开头
def isNumLeters(s):
    s = str(s)
    if s == '':
        return False
    if len(s) < 2:
        if re.match('^[0-9a-zA-Z]+$', s[0]):
            return True
        else:
            return False
    else:
        if re.match('^[0-9a-zA-Z]+$', s[0]) and re.match('^[0-9a-zA-Z_-]+$', s[1:]):
            return True
        else:
            return False

# 扩展replace()方法，去掉字符串中的指定字符，并返回去掉后的子字符串
# 传参说明：
# myString 原字符串
# oldSubStr 要替换的子字符串
# newSubStr 替换后的子字符串
# count 要替换的次数，默认为-1（负数-全部替换，0-不替换，1-替换第1个，n-替换前n个）
# caseSensitive（1-区分大小写，其他-不区分大小写）
def myReplace(myString, oldSubStr, newSubStr, count=-1, caseSensitive='1'):
    # 处理传参，不合法的时候强制转换为需要的类型
    oldSubStr = str(oldSubStr)
    newSubStr = str(newSubStr)
    myString = str(myString)
    if not isinstance(count, int):
        count = -1

    # oldSubStr为空时不做替换，直接返回原字符串
    if oldSubStr == '':
        return myString

    # 区分大小写时，直接调用replace()方法处理
    if str(caseSensitive) == '1':
        myString = myString.replace(oldSubStr, newSubStr, count)
        return myString

    # 不区分大小写时，oldSubStr在myString中不存在
    tem = countSubString(oldSubStr, myString, '1')
    if not tem['flag']:
        return myString

    # 不区分大小写时，oldSubStr在myString中存在
    oldSubStr = oldSubStr.lower()
    if count == 0:
        return myString
    elif count < 0:
        for i in tem['index_start']:
            myString = oldSubStr.join(myString.split(myString[i:i + len(oldSubStr)]))
    else:
        for i in tem['index_start'][:count]:
            myString = oldSubStr.join(myString.split(myString[i:i + len(oldSubStr)]))
    myString = myString.replace(oldSubStr, newSubStr, count)
    return myString

# 判断给定的字符串是否含有中文
def is_zh(s):
    # zhmodel = re.compile(u'[\u4e00-\u9fa5]')  # 只判断汉字
    # 3000-303F
    zhmodel = re.compile(u'[\u3002-\uffee]')  # 判断中文状态下的标点符号
    match = zhmodel.search(str(s))
    if match:
        return True
    else:
        return False

# 判断给定的字符串是否含有英文
def is_leter(str):
  my_re = re.compile(r'[A-Za-z]',re.S)
  res = re.findall(my_re,str)
  if len(res):
      return True
  else:
      return False

# 自定义判断header是否符合格式要求，返回的列表如果有数据表示不符合要求
def is_headers_ok(header):
    header = str(header).strip('$')
    errorHeaders = []
    if header:
        temList = header.split('$')
        for item in temList:
            if '#' not in item or is_zh(item) or not is_leter(item.split('#')[0]):
                errorHeaders.append(item)
    return errorHeaders

# 获取header并处理成字典
def get_headers(header):
    header = str(header).strip('$')
    header_Dict = {}
    if header:
        if '#' not in header or is_zh(header) or not is_leter(header):
            return 'header头信息格式不正确，请检查！'
        else:
            temList = header.split('$')
            for item in temList:
                if '#' not in item or not is_leter(item.split('#')[0]):
                    return '【%s】设置错误，请检查！' %item
                else:
                    tem = item.split('#')
                    if is_leter(tem[0]):
                        header_Dict[tem[0]] = tem[1]
    return header_Dict


# 计算一个字符letter在给定的list中的位置
def countLetter(letter, myStrList):
    if len(letter) != 1:
        return False
    if letter not in myStrList:
        return False
    tem = []
    for i in range(0,len(myStrList)):
        if letter == myStrList[i]:
            tem.append(i)
    return tem

# 查找字符串childStr在字符串fatherStr中出现的次数及开始位置，lettersToLower设置为0时区分大小写，设置为非0时不区分大小写
# 返回结果格式：
# {
# 'childStr_original': 'abcabc', (用来匹配的原始子字符串)
# 'fatherStr_original': 'abcabcabcabcabcabc', (用来匹配的原始父字符串)
# 'flag': True, (True-匹配成功，False-匹配失败)
# 'count': 5, (匹配到的个数)
# 'index_start': [0, 3, 6, 9, 12] (匹配到的下标索引列表)
# }
def countSubString(childStr, fatherStr, lettersToLower = '0'):
    resDict = {}
    childStr = str(childStr)
    fatherStr = str(fatherStr)
    resDict['childStr_original'] = childStr
    resDict['fatherStr_original'] = fatherStr

    if str(lettersToLower) != '0':
        childStr = childStr.lower()
        fatherStr = fatherStr.lower()

    # 对比用的子字符串如果为空或者不在目标字符串中，直接返回False
    if childStr not in fatherStr or len(childStr) < 1:
        resDict['flag'] = False
        resDict['count'] = 0
        resDict['index_start'] = []
        return resDict

    # 两个字符串相同时快速处理
    if childStr == fatherStr:
        resDict['flag'] = True
        resDict['count'] = 1
        resDict['index_start'] = [0]
        return resDict

    fatherStr = list(fatherStr)
    childStrList = list(childStr)
    tem, tem2, tem3 = [], [], []
    for item in childStrList:
        a = countLetter(item, fatherStr)
        tem.append(a)
    for jj in range(0, len(tem)):
        tem2.append([x - jj for x in tem[jj]])
    for m in tem2:
        tem3 = list(set(tem2[0]).intersection(m))
    tem3.sort()
    resDict['flag'] = True
    resDict['count'] = len(tem3)
    resDict['index_start'] = tem3
    return resDict

# 给定起始数，结尾数及步长，计算从起始数开始，以步长为间隔，到结尾数为止的所有数字的和，可以指定保留结果小数位数
def mySum(startNum, endNum, step, decimalLen=-1):
    # 传参类型不对时直接返回false
    if not isinstance(startNum, (int, float)) or not isinstance(endNum, (int, float)) or not isinstance(step, (
    int, float)):
        return False

    # 保留小数位数decimalLen如果设置的不是0或者正整数，默认都使用startNum, endNum, step三个参数中最大的小数位数
    if not isinstance(decimalLen, int) or decimalLen < 0:
        decimalLen_startNum, decimalLen_endNum, decimalLen_step = 0, 0, 0
        decimalLen_startNum_list = str(startNum).split('.')
        decimalLen_endNum_list = str(endNum).split('.')
        decimalLen_step_list = str(step).split('.')
        if len(decimalLen_startNum_list) == 2:
            decimalLen_startNum = len(decimalLen_startNum_list[1])
        if len(decimalLen_endNum_list) == 2:
            decimalLen_endNum = len(decimalLen_endNum_list[1])
        if len(decimalLen_step_list) == 2:
            decimalLen_step = len(decimalLen_step_list[1])
        decimalLen = max([decimalLen_startNum, decimalLen_endNum, decimalLen_step])

    # 步长为0或者开始的数字大于等于结尾的数字时，返回开始数和结尾数的和
    if step == 0 or startNum >= endNum:
        sum = startNum + endNum
        if decimalLen == 0:
            sum = int(sum)
        else:
            sum = round(sum, decimalLen)
        return sum

    # 步长不能小于0，否则设置为默认值1
    if step < 0:
        step = 1
    sum = 0
    while True:
        sum = sum + startNum
        startNum = startNum + step
        if startNum >= endNum:
            startNum = endNum
            sum = sum + startNum
            break
    if decimalLen == 0:
        sum = int(sum)
    else:
        sum = round(sum, decimalLen)
    return sum